package com.example.unifiedinterface.sender;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.example.unifiedinterface.entity.BaseRequestParam;
import com.example.unifiedinterface.entity.BaseResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: 19239
 * @Description: 接口发送请求基类
 * @Date: 2024/5/21
 * @Version: 1.0
 */
public abstract class BaseUnifiledSender<T> {

    /**
     * 获取请求地址
     *
     * @return
     */
    protected abstract String getUrl();

    /**
     * 获取请求名称
     *
     * @return
     */
    protected abstract String getRequestName();

    /**
     * 获取请求模板
     *
     * @return
     */
    protected abstract RestTemplate getRestTemplate();

    /**
     * 客户端认证信息用户名
     *
     * @return
     */
    protected abstract String getUsername();

    protected abstract String getPassword();

    private static Log log = LogFactory.getLog(BaseUnifiledSender.class);

    /**
     * 第一个 <T> 定义了方法级的泛型类型参数 T。这意味着：
     * <p>
     * T 是一个占位符，代表某种未知的具体类型。
     * 它被用来指定方法的返回类型 BaseResponse<T>，意味着这个方法将返回一个 BaseResponse 类型的对象，其中的具体类型由调用时的实际参数决定。
     *
     * @param requestParam
     * @param <T>
     * @return
     */

    public <T> BaseResponse<T> send(BaseRequestParam<T> requestParam) {
        log.info("请求服务：" + getRequestName());
        if (requestParam == null) {
            log.error("请求参数为空");
            return null;
        }
        //设置请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.set("token", requestParam.getRequestHead().getToken());
        httpHeaders.set("requestType", requestParam.getRequestHead().getRequestType());
        try {
            //获取调用端服务器地址
            String hostAddress = InetAddress.getLocalHost().getHostAddress();
            httpHeaders.set("ip", hostAddress);
        } catch (UnknownHostException e) {
            throw new RuntimeException(e);
        }
        //设置入参
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("data", requestParam.getData());
        paramMap.put("otherInfo", requestParam.getOtherInfo());

        /**发送请求**/
        HttpEntity<Map> entity = new HttpEntity<>(paramMap, httpHeaders);

        String response = getResponse(entity);
        if (response != null) {
            BaseResponse baseResponse = new BaseResponse();
            JSONObject jsonObject = JSON.parseObject(response);
            baseResponse.setCode(jsonObject.getString("code"));
            baseResponse.setMessage(jsonObject.getString("message"));
            baseResponse.setData(jsonObject);
            return baseResponse;

        } else {
            return null;
        }

    }

    private String getResponse(HttpEntity<Map> entity) {
        /**
         * SerializerFeature.WriteDateUseDateFormat：这是一个序列化特性标志，告诉Fastjson在序列化时使用指定的日期格式（上面提到的"yyyy-MM-dd HH:mm:ss"）。如果不设置这个特性，Fastjson可能会使用默认的日期时间格式，这可能导致日期时间的显示不符合预期
         */
        log.info("请求参数,转化日期：" + JSON.toJSONStringWithDateFormat(entity.getBody(), "yyyy-MM-dd HH:mm:ss", SerializerFeature.WriteDateUseDateFormat));
        ResponseEntity<String> response = null;
        List<String> requestType = entity.getHeaders().get("requestType");
        if (StringUtils.endsWithIgnoreCase("post", requestType.get(0))) {
            response = getRestTemplate().exchange(getUrl(), org.springframework.http.HttpMethod.POST, entity, String.class);
        } else {
            response = getRestTemplate().exchange(getUrl(), org.springframework.http.HttpMethod.GET, entity, String.class);
        }

        if (response != null) {

            String body = response.getBody();
            if (org.apache.commons.lang3.StringUtils.isBlank(body)) {
                log.info(getUrl() + " --" + "请求服务：" + getRequestName() + "成功, " + "返回结果为空");
            } else {
                log.info("请求服务：" + getRequestName() + "成功, " + "返回结果为：" + body);

            }
            return body;
        } else {
            log.error("请求服务：" + getRequestName() + "失败");
            return null;
        }
    }

}
